#include <stdafx.h>
#include "VcClientUtils.h"


boost::shared_ptr<CHANNEL_ENTRY_POINTS> rdc_transport::MakeCopy(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
    // Copy channel entries
    PCHANNEL_ENTRY_POINTS pChannelEntryPoints =
        reinterpret_cast<PCHANNEL_ENTRY_POINTS>(::LocalAlloc(LPTR, pEntryPoints->cbSize));

    if (pChannelEntryPoints == NULL)
        throw std::bad_alloc("Cannot allocate memory for CHANNEL_ENTRY_POINTS");

    // Add resource guard
    boost::shared_ptr<CHANNEL_ENTRY_POINTS> psChannelEntryPoints(pChannelEntryPoints, &::LocalFree);

    if(memcpy_s(pChannelEntryPoints, pEntryPoints->cbSize, pEntryPoints, pEntryPoints->cbSize)) 
        throw std::runtime_error(std::string(__FUNCTION__) + " Cannot copy virtual channel entry point structure"); 

    return psChannelEntryPoints;
}

void rdc_transport::InitChannel(PCHANNEL_ENTRY_POINTS pEntryPoints, const char* name, ULONG options, PCHANNEL_INIT_EVENT_FN callback)
{
    CHANNEL_DEF defChannel;
    ::memset(&defChannel, 0, sizeof(CHANNEL_DEF));
    
    if(::strcpy_s(defChannel.name, sizeof(defChannel.name), name))
        throw std::runtime_error(std::string(__FUNCTION__) + " Cannot config channel definition");
    defChannel.options = options;

    LPHANDLE phChannel = NULL;
    UINT uiRes = pEntryPoints->pVirtualChannelInit(
        reinterpret_cast<LPVOID*>(&phChannel),
        &defChannel,
        sizeof(defChannel) / sizeof(CHANNEL_DEF),
        VIRTUAL_CHANNEL_VERSION_WIN2000,
        callback);

    if ((uiRes != CHANNEL_RC_OK) || !(defChannel.options & CHANNEL_OPTION_INITIALIZED))
        throw std::runtime_error(std::string(__FUNCTION__) + " Cannot init virtual channel");
}